package io.renren.ssh;

import com.alibaba.fastjson.JSONObject;
import io.renren.modules.project.entity.ModuleEntity;
import io.renren.modules.project.service.ModuleService;
import io.renren.modules.sys.entity.SysUserTokenEntity;
import io.renren.modules.sys.service.ShiroService;
import io.renren.modules.systemconfig.entity.SystemConfigServersEntity;
import lombok.extern.java.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/log/{moduleId}/{token}")
@Log
public class RuntimeLogWebsocketServer {
    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext applicationContext) {
        RuntimeLogWebsocketServer.applicationContext = applicationContext;
    }

    private static Logger logger = LoggerFactory.getLogger(RuntimeLogWebsocketServer.class);


    public static ConcurrentHashMap<String,RuntimeLogConnection> ModuleId_LogConn =new ConcurrentHashMap<>();

    public static ConcurrentHashMap<String,String>   session_ModuleId = new ConcurrentHashMap<>();

    private Session ConcurrentSession  = null;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "moduleId") Long moduleId, @PathParam(value = "token") String token) {
        try {

            ShiroService shiroService=applicationContext.getBean(ShiroService.class);
            SysUserTokenEntity tokenEntity =  shiroService.queryByToken(token);
            if(token == null||tokenEntity==null||tokenEntity.getUserId()==null){
                SshResponse response = new SshResponse(1,"登录失败请重新登录！","/error");
                try{sendMessage(session, JSONObject.toJSONString(response));}catch (Exception e1){
                    e1.printStackTrace();
                }
                session.close();
            }

            Long userId=tokenEntity.getUserId();



            if(!ModuleId_LogConn.containsKey(moduleId+"-"+userId)){
                initSSHConnect(moduleId,moduleId+"-"+userId);
            }

            new Thread(new Runnable() {
                @Override
                public void run() {
                    Long total = 0l;
                    while(ModuleId_LogConn.containsKey(moduleId+"-"+userId)){
                        RuntimeLogConnection rlc = ModuleId_LogConn.get(moduleId+"-"+userId);
                        if(rlc==null){
                            break;
                        }
                        try{
                            StringBuffer sb = rlc.getSession().exec("wc -l "+ rlc.getEntity().getDeployPath()+"/nohup.out");
                            String[] result = sb.toString().split("\n");
                            if(result.length>0){
                                String [] resultList = result[0].trim().split("\\s+");
                                if(resultList.length>0){
                                   long tempTotal = Long.parseLong(resultList[0]);
                                    if(tempTotal-total>10){
                                        System.out.println("sed -n '"+(tempTotal-10)+","+tempTotal+"p' "+ rlc.getEntity().getDeployPath()+"/nohup.out");
                                        sb = rlc.getSession().exec("sed -n '"+(tempTotal-10)+","+tempTotal+"p' "+ rlc.getEntity().getDeployPath()+"/nohup.out");
                                        SshResponse response = new SshResponse(0,sb.toString(),String.valueOf(tempTotal));
                                        sendMessage(session, JSONObject.toJSONString(response));
                                    }else if(tempTotal-total>0){
                                        System.out.println("sed -n '"+total+","+tempTotal+"p' "+ rlc.getEntity().getDeployPath()+"/nohup.out");
                                        sb = rlc.getSession().exec("sed -n '"+total+","+tempTotal+"p' "+ rlc.getEntity().getDeployPath()+"/nohup.out");
                                        //List<String> list = new ArrayList<>(Arrays.asList(sb.toString().split("\n")));
                                        //System.out.println(JSONObject.toJSONString(list));
                                        SshResponse response = new SshResponse(0,sb.toString(),String.valueOf(tempTotal));
                                        sendMessage(session, JSONObject.toJSONString(response));
                                    }else{
                                        SshResponse response = new SshResponse(0,"",String.valueOf(tempTotal));
                                        sendMessage(session, JSONObject.toJSONString(response));
                                    }
                                    total = tempTotal;
                                    System.out.println("total:"+total);
                                    Thread.sleep(3000);
                                }
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }

                    }
                }
            }).start();

//            StringBuffer sb = null;
//            try{
//                sb = ModuleId_LogConn.get(moduleId+"-"+userId).getSession().exec("pwd");
//            }catch (JSchException e){
//                initSSHConnect(moduleId,moduleId+"-"+userId);
//                sb = ModuleId_LogConn.get(moduleId+"-"+userId).getSession().exec("pwd");
//            }
            ConcurrentSession = session;
//            ServerId_SSHConn.get(serverId+"-"+userId).setPwd(sb.toString().replace("\n","").replace("\r\n",""));
//            SshResponse sr = new SshResponse(0,"登录成功!\n服务器时间："+ DateUtils.formatDefault(new Date()),sb.toString());
//            System.out.println("ssh返回:"+sb.toString());
//            sendMessage(session, JSONObject.toJSONString(sr));
            session_ModuleId.put(session.getId(),moduleId+"-"+userId);
        } catch (Exception e) {
            e.printStackTrace();
            SshResponse response = new SshResponse(1,"服务器IO异常！","/error");
            try{sendMessage(session, JSONObject.toJSONString(response));}catch (Exception e1){
                e1.printStackTrace();
            }
        }
    }

    private void initSSHConnect(Long moduleId,String key) throws Exception{
        ModuleService moduleService=applicationContext.getBean(ModuleService.class);
        ModuleEntity se = moduleService.getModuleServerById(moduleId);
        if(se!=null){
            RuntimeLogConnection  conn  = new RuntimeLogConnection(se,20000);

            SSHClient client = new SSHClient(se.getServer());
            conn.setSession(client);
            ModuleId_LogConn.put(key,conn);
        }else{
            throw new SshTimeoutException("无法加载服务器信息!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(ConcurrentSession!=null&&ConcurrentSession.getId()!=null&&session_ModuleId.containsKey(ConcurrentSession.getId())){
            RuntimeLogConnection conn = ModuleId_LogConn.get(session_ModuleId.get(ConcurrentSession.getId()));
            try{
                conn.getSession().close();
            }catch (Exception e){
                e.printStackTrace();
            }
            ModuleId_LogConn.remove(session_ModuleId.get(ConcurrentSession.getId()));
            session_ModuleId.remove(ConcurrentSession.getId());
            logger.info("关闭 ssh 连接："+ conn.getEntity().getServer().getName());

        }

        logger.info("连接关闭！");
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("收到来自窗口 {}  的信息:{}" ,session.getId(), message);


    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误");
        error.printStackTrace();
    }
    public static void sendMessage(Session session,String message) throws IOException {
        log.info(message);
        session.getBasicRemote().sendText(message);
    }

}